package org.mybatis.generator.plugins;

import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.lang.reflect.Field;
import java.util.List;

public class SelectSelectivePlugin extends PluginAdapter {
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

   /* @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        topLevelClass.addImportedType("java.util.List");
        return true;
    }*/

    @Override
    public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
        Method method = new Method("selectSelective");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setAbstract(true);
        FullyQualifiedJavaType returnType = new FullyQualifiedJavaType("List<" + introspectedTable.getBaseRecordType() + ">");
        method.setReturnType(returnType);

//        method.setReturnType(FullyQualifiedJavaType.getNewListInstance());  // 返回 List

        FullyQualifiedJavaType paramType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
        method.addParameter(new Parameter(paramType, "record"));

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);
        interfaze.addImportedType(FullyQualifiedJavaType.getNewListInstance());
        interfaze.addMethod(method);
        return true;

        // 添加注解（如果需要）
        // method.addAnnotation("@Param(\"record\")");
    }

    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        // 添加 `selectSelective` 到 XML
        XmlElement select = new XmlElement("select");
        select.addAttribute(new Attribute("id", "selectSelective"));
        select.addAttribute(new Attribute("resultMap", introspectedTable.getBaseResultMapId()));
        select.addAttribute(new Attribute("parameterType", introspectedTable.getBaseRecordType()));

        StringBuilder sb = new StringBuilder();
        sb.append("SELECT \n\t")
                .append("<include refid=\"Base_Column_List\" /> \n\t")
                .append("FROM " + introspectedTable.getFullyQualifiedTableNameAtRuntime());

        select.addElement(new TextElement(sb.toString()));

        // 动态 WHERE 条件部分
        XmlElement where = new XmlElement("where");
        // 遍历每个字段，动态生成查询条件
        introspectedTable.getAllColumns().forEach(column -> {
            XmlElement ifElement = new XmlElement("if");
            ifElement.addAttribute(new Attribute("test", column.getJavaProperty() + " != null"));
            ifElement.addElement(new TextElement("AND " + column.getActualColumnName() + " = #{" + column.getJavaProperty() + ",jdbcType=" + column.getJdbcTypeName() + "}"));
            where.addElement(ifElement);
        });
        select.addElement(where);
        document.getRootElement().addElement(select);
        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        try {
            Field field = sqlMap.getClass().getDeclaredField("isMergeable");
            field.setAccessible(true);
            field.setBoolean(sqlMap, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}
